<!DOCTYPE html>
<html>

<head>
  <title>cannon.js - sph demo</title>
  <meta charset="utf-8">
  <link rel="stylesheet" href="css/style.css" type="text/css" />
  <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>

<body>
  <script src="../../feng3d/out/feng3d.js"></script>
  <script src="../out/cannon.js"></script>
  <script src="../build/cannon.demo.js"></script>
  <script src="../libs/dat.gui.js"></script>
  <script src="../libs/Three.js"></script>
  <script src="../libs/TrackballControls.js"></script>
  <script src="../libs/Detector.js"></script>
  <script src="../libs/Stats.js"></script>
  <script src="../libs/smoothie.js"></script>
  <script>

    var demo = new CANNON.Demo();
    var nx = 4, ny = 4, nz = 15, w = 10, h = 5, mass = 0.01;
    var walls = true;


    // Test scalability - add scenes for different number of particles
    demo.addScene((nx * ny * nz) + " particles", function ()
    {

      // Create world
      var world = demo.getWorld();
      var sph = new CANNON.SPHSystem();
      sph.density = 1;
      sph.viscosity = 0.03;
      sph.smoothingRadius = 1.0;
      world.subsystems.push(sph);

      // Tweak contact properties.
      world.defaultContactMaterial.contactEquationStiffness = 1e11; // Contact stiffness - use to make softer/harder contacts
      world.defaultContactMaterial.contactEquationRelaxation = 2; // Stabilization time in number of timesteps

      // Max solver iterations: Use more for better force propagation, but keep in mind that it's not very computationally cheap!
      world.solver.iterations = 10;

      world.gravity.set(0, 0, -10);

      // Materials
      var material = new CANNON.Material();
      var material_material = new CANNON.ContactMaterial(material, material, {
        friction: 0.06,
        restitution: 0.0
      });
      world.addContactMaterial(material_material);

      // ground plane
      var groundShape = new CANNON.Plane();
      var groundBody = new CANNON.Body({
        mass: 0,
        material: material
      });
      groundBody.addShape(groundShape);
      world.addBody(groundBody);
      demo.addVisual(groundBody);

      if (walls)
      {

        // plane -x
        var planeShapeXmin = new CANNON.Plane();
        var planeXmin = new CANNON.Body({
          mass: 0,
          material: material
        });
        planeXmin.addShape(planeShapeXmin);
        planeXmin.quaternion.fromAxisAngle(new CANNON.Vector3(0, 1, 0), Math.PI / 2);
        planeXmin.position.set(-w * 0.5, 0, 0);
        world.addBody(planeXmin);

        // Plane +x
        var planeShapeXmax = new CANNON.Plane();
        var planeXmax = new CANNON.Body({ mass: 0, material: material });
        planeXmax.addShape(planeShapeXmax);
        planeXmax.quaternion.fromAxisAngle(new CANNON.Vector3(0, 1, 0), -Math.PI / 2);
        planeXmax.position.set(w * 0.5, 0, 0);
        world.addBody(planeXmax);

        // Plane -y
        var planeShapeYmin = new CANNON.Plane();
        var planeYmin = new CANNON.Body({ mass: 0, material: material });
        planeYmin.addShape(planeShapeYmin);
        planeYmin.quaternion.fromAxisAngle(new CANNON.Vector3(1, 0, 0), -Math.PI / 2);
        planeYmin.position.set(0, -h * 0.5, 0);
        world.addBody(planeYmin);

        // Plane +y
        var planeShapeYmax = new CANNON.Plane();
        var planeYmax = new CANNON.Body({ mass: 0, material: material });
        planeYmax.addShape(planeShapeYmax);
        planeYmax.quaternion.fromAxisAngle(new CANNON.Vector3(1, 0, 0), Math.PI / 2);
        planeYmax.position.set(0, h * 0.5, 0);
        world.addBody(planeYmax);
      }

      // Create particles
      var rand = 0.1;
      for (var i = 0; i !== nx; i++)
      {
        for (var j = 0; j !== ny; j++)
        {
          for (var k = 0; k !== nz; k++)
          {
            var particle = new CANNON.Body({
              mass: mass,
              material: material
            });
            particle.addShape(new CANNON.Particle());
            particle.position.set((i + (Math.random() - 0.5) * rand + 0.5) * w / nx - w * 0.5,
              (j + (Math.random() - 0.5) * rand + 0.5) * h / ny - h * 0.5,
              k * h / ny);
            world.addBody(particle);
            sph.add(particle);
            demo.addVisual(particle);
          }
        }
      }
    });

    demo.start();

  </script>
</body>

</html>